route.ts 1.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import { NextRequest, NextResponse } from "next/server";
  2. async function handle(
  3. req: NextRequest,
  4. { params }: { params: { action: string; key: string[] } },
  5. ) {
  6. const requestUrl = new URL(req.url);
  7. const endpoint = requestUrl.searchParams.get("endpoint");
  8. if (req.method === "OPTIONS") {
  9. return NextResponse.json({ body: "OK" }, { status: 200 });
  10. }
  11. const [...key] = params.key;
  12. // only allow to request to *.upstash.io
  13. if (!endpoint || !new URL(endpoint).hostname.endsWith(".upstash.io")) {
  14. return NextResponse.json(
  15. {
  16. error: true,
  17. msg: "you are not allowed to request " + params.key.join("/"),
  18. },
  19. {
  20. status: 403,
  21. },
  22. );
  23. }
  24. // only allow upstash get and set method
  25. if (params.action !== "get" && params.action !== "set") {
  26. console.log("[Upstash Route] forbidden action ", params.action);
  27. return NextResponse.json(
  28. {
  29. error: true,
  30. msg: "you are not allowed to request " + params.action,
  31. },
  32. {
  33. status: 403,
  34. },
  35. );
  36. }
  37. const targetUrl = `${endpoint}/${params.action}/${params.key.join("/")}`;
  38. const method = req.method;
  39. const shouldNotHaveBody = ["get", "head"].includes(
  40. method?.toLowerCase() ?? "",
  41. );
  42. const fetchOptions: RequestInit = {
  43. headers: {
  44. authorization: req.headers.get("authorization") ?? "",
  45. },
  46. body: shouldNotHaveBody ? null : req.body,
  47. method,
  48. // @ts-ignore
  49. duplex: "half",
  50. };
  51. console.log("[Upstash Proxy]", targetUrl, fetchOptions);
  52. const fetchResult = await fetch(targetUrl, fetchOptions);
  53. console.log("[Any Proxy]", targetUrl, {
  54. status: fetchResult.status,
  55. statusText: fetchResult.statusText,
  56. });
  57. return fetchResult;
  58. }
  59. export const POST = handle;
  60. export const GET = handle;
  61. export const OPTIONS = handle;
  62. export const runtime = "edge";